package com.hlkj.baojin.dao.repository;

import com.hlkj.baojin.constant.BaseRepository;
import com.hlkj.baojin.dao.IDictDAO;
import com.hlkj.baojin.entity.*;
import com.hlkj.baojin.entity.dto.*;
import com.hlkj.baojin.utils.bean.Page;
import com.hlkj.baojin.utils.lang.DateUtil;
import com.mongodb.client.result.UpdateResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.BooleanOperators;
import org.springframework.data.mongodb.core.aggregation.ComparisonOperators;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import java.util.*;
import java.util.stream.Collectors;

import static org.springframework.data.mongodb.core.aggregation.Aggregation.match;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.project;
import static org.springframework.data.mongodb.core.aggregation.ArrayOperators.Filter.filter;

/**
 * @author lzx
 * @created with: baojin
 * @package com.hlkj.baojin.dao.repository
 * @description:
 * @date 2018/12/17 12:43
 * @modified By:
 * @Copyright © 2018 HAILIANG Info. Tech Ltd. All rights reserved.
 */
@Repository
public class RealDataRepository extends BaseRepository<RealData> {

    @Autowired
    private IDictDAO dictDAO;


    public RealDataRepository(MongoTemplate mongoTemplate) {
        super(mongoTemplate);
    }
    public ModelList<RealData> findList(RealSearchDTO realSearchDTO) {
        Query query = new Query();
        Query dQuery = new Query();
        if (realSearchDTO.getStatus()!=null) {
            query.addCriteria(Criteria.where("status").is(realSearchDTO.getStatus()));
        }
        if (!StringUtils.isEmpty(realSearchDTO.getCompanyId())) {
            query.addCriteria(Criteria.where("deptId").is(realSearchDTO.getCompanyId()));
            dQuery.addCriteria(Criteria.where("belongCompany").is(realSearchDTO.getCompanyId()));
        }
        if (realSearchDTO.getMonitorType()!=null) {
            dQuery.addCriteria(Criteria.where("monitorType").is(realSearchDTO.getMonitorType()));
        }

        List<String> collect = mongoTemplate.find(dQuery, Device.class).stream().map(Device::getId).collect(Collectors.toList());
        query.addCriteria(Criteria.where("deviceId").in(collect));



        if (realSearchDTO.getPage()!=null&&realSearchDTO.getSize()!=null) {
            query.with(new Page(realSearchDTO.getPage(), realSearchDTO.getSize()));
        }

        List<RealData> realList = mongoTemplate.find(query, RealData.class);
        long count = mongoTemplate.count(query, RealData.class);
        ModelList<RealData> deviceModelList = new ModelList<>(realList, count);
        return deviceModelList;
    }

    public void updateReal(Long errTime) {
        Query query = new Query();
        query.addCriteria(Criteria.where("updateTime").lt(System.currentTimeMillis()-errTime).and("status").is(0));
        Update update = Update.update("status", 1);
        List<RealData> realData = mongoTemplate.find(query, RealData.class);
        mongoTemplate.updateMulti(query, update, RealData.class);
        realData.forEach(realData1 -> {
            DeviceErrLog deviceErrLog = mongoTemplate.findOne(new Query(Criteria.where("deviceId").is(realData1.getDeviceId())), DeviceErrLog.class);
            //修改设备的故障状态
            mongoTemplate.updateMulti( new Query(Criteria.where("id").is(realData1.getDeviceId())), Update.update("status", 1), Device.class);
            if(deviceErrLog==null){
                deviceErrLog=new DeviceErrLog(realData1.getDeviceId(), Collections.singletonList(new Details(1, System.currentTimeMillis())));
            }else {
                if(deviceErrLog.getDetails().stream().noneMatch(details -> details.getOkTime() == null)){
                    deviceErrLog.getDetails().add(new Details(deviceErrLog.getDetails().stream().map(Details::getOrder).max(Comparator.naturalOrder()).get()+1, System.currentTimeMillis()));
                }
            }
            mongoTemplate.save(deviceErrLog);
        });
    }
    public void updateReal(String deviceId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("deviceId").in(deviceId).and("details").elemMatch(Criteria.where("okTime").is(null)));
        Update update = new Update();
        update.set("details" + ".$.okTime", System.currentTimeMillis());
        UpdateResult updateResult = mongoTemplate.updateMulti(query, update, DeviceErrLog.class);
    }

    public long findCurDayLog(String id) {
        Query query = new Query(Criteria.where("deviceId").is(id).and("createTime").gte(DateUtil.getOfDayFirst(new Date()).getTime()).lte(DateUtil.getOfDayLast(new Date()).getTime()));
       return mongoTemplate.count(query, DeviceStatusDataLog.class);


    }

    public void saveStatusDataLog(DeviceStatusDataLog deviceStatusDataLog) {
        mongoTemplate.save(deviceStatusDataLog);
    }

    public void addStatusDataLog(String id, StatusDataLog asList) {
        Query query = new Query(Criteria.where("deviceId").is(id).and("createTime").gte(DateUtil.getOfDayFirst(new Date()).getTime()).lte(DateUtil.getOfDayLast(new Date()).getTime()));
        Update update = new Update();
        update.push("details",asList);
        mongoTemplate.updateMulti(query, update, DeviceStatusDataLog.class);
    }

    public DeviceStatusDataLog waveMsg(WaveSearchDTO waveSearchDTO) {
        Date date;
        if (waveSearchDTO.getTime() == null) {
            date = new Date();
        } else {
            date = new Date(waveSearchDTO.getTime());
        }
        Query query = new Query(Criteria.where("deviceId").is(waveSearchDTO.getDeviceId()).and("createTime").gte(DateUtil.getOfDayFirst(date).getTime()).lte(DateUtil.getOfDayLast(date).getTime()));

        return mongoTemplate.findOne(query, DeviceStatusDataLog.class);
    }

    public List<DeviceStatusDataLog> getAlarmWaveMsg(String deviceId, Long startTime, Long endTime) {
        Aggregation aggregation = newAggregation(match(Criteria.where("deviceId").is(deviceId)),
                project().and(filter("details")
                        .as("item")
                        .by(BooleanOperators.And.and(ComparisonOperators.Lte.valueOf("item.realTime").lessThanEqualToValue(endTime + 60000),
                         ComparisonOperators.Gte.valueOf("item.realTime").greaterThanEqualToValue(startTime - 60000))))
                        .as("details")

        );
        List<DeviceStatusDataLog> results = mongoTemplate.aggregate(aggregation, "deviceStatusDataLog", DeviceStatusDataLog.class).getMappedResults();
        return results;
//        Query query = new Query(Criteria.where("deviceId").is(deviceId));
//        if (startTime != null && endTime != null) {
////            query.addCriteria(Criteria.where("createTime").gte(startTime).lte(endTime));
//            query.addCriteria(Criteria.where("details.realTime").gte(startTime).lte(endTime));
//        }
//        return mongoTemplate.find(query, DeviceStatusDataLog.class);
    }

    public void addDict(Integer type, String key, String companyId) {
//        1公司 2 设备
        switch (type){
            case 1:
                Dict company = dictDAO.findByType(type);
                if(company!=null){
                    company.getKeys().add(key);
                    dictDAO.save(company);
                }else {
                    dictDAO.save(new Dict(new HashSet<>(Collections.singletonList(key)),type,"公司类型",null));
                }
                break;
            case 2:
                Dict device = dictDAO.findByTypeAndCompanyId(type,companyId);
                if(device!=null){
                    device.getKeys().add(key);
                    dictDAO.save(device);
                }else {
                    dictDAO.save(new Dict(new HashSet<>(Collections.singletonList(key)),type,"设备类型",companyId));
                }
                break;
             default:
                 break;
        }

    }
}
